class Student(object):
    def __init__(self,name):
        self.name=name

    def __str__(self):
        return 'Student object(name:%s)' %self.name

    __repr__=__str__


print(Student('Michael_qiaodan'))

s=Student('hws')
print(s)
# 如果一个类想被用于for ... in循环，类似list或tuple那样，就必须实现一个__iter__()方法，
# 该方法返回一个迭代对象，然后，Python的for循环就会不
# 断调用该迭代对象的__next__()方法拿到循环的下一个值，直到遇到StopIteration
# 错误时退出循环。
class Fib(object):
    def __init__(self):
        self.a,self.b=0,1 #初始化斐波那契数的前两个

    def __iter__(self):
        return  self #实例本身就是迭代对象，返回自己

    def __next__(self):
        self.a,self.b =self.b,self.a+self.b
        if self.a>10:
            raise StopIteration
        return  self.a


for n in Fib():
    print(n)


# 要表现得像list那样按照下标取出元素，需要实现__getitem__()方法：
class Fib1(object):
    def __getitem__(self, n):
        a,b=1,1
        for x in  range(n):
            a,b=b,a+b
        return  a

f=Fib1()
print(f[0])
print(f[1])
print(f[2])
print(f[3])

#要想实现能切片还得判断类型原因是__getitem__()传入的参数可能是一个int，也可能是一个切片对象slice，所以要做判断：

class Fib2(object):
    def __getitem__(self, n):
        if isinstance(n,int):#当n是整数的时候是索引
            a,b=1,1
            for x in range(n):
                a,b=b,a+b
            return  a
        if isinstance(n,slice):
            start=n.start
            stop=n.stop
            if start is None:
                start=0
            a,b=1,1
            L=[]
            for x in range(stop):
                if x >= start:
                    L.append(a)
                a,b=b,a+b
            return L

f=Fib2()

print(f[0:5])
print(f[:10])
#但是没有对step参数作处理：
print(f[:10:2])

#__getattr__当我们调用类的方法或属性时，如果不存在，就会报错。比如定义Student类：

class Student(object):
    def __init__(self):
        self.name='hws!'

s=Student()
print(s.name)
try:
    print(s.score)
except:
    print("异常拉，变量不存在")
#要避免这个错误，除了可以加上一个score属性外，Python还有另一个机制，那就是写一个__getattr__()方法，动态返回一个属性

class Student2(object):
    def __init__(self):
        self.name='pph!'
    def __getattr__(self, item):#当调用不存在的属性的时候，python这个函数会获得本不存在的属性
        if item=='score':
            return 99
    def __getattr__(self, attr):#返回函数也是可以的
        if attr=='age':
            return lambda: 25
serr=Student2()
print(serr.name)
try:
    print(serr.score)
except:
    print("异常拉，变量不存在")

print(serr.age())

#注意：只有在没有找到属性的情况下，才调用__getattr__，已有的属性，比如name，不会在__getattr__中查找。
class Student3(object):
    def __init__(self, name):
        self.name = name

    def __call__(self):
        print('My name is %s.' % self.name)

s = Student3('er')
s()






